package com.wei.czz.framework.common.helper;

import com.wei.czz.common.dto.common.NameValue;
import com.wei.czz.common.dto.common.UploadDto;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.common.FileTypeEnum;
import com.wei.czz.common.enums.common.TaskModeEnum;
import com.wei.czz.common.enums.common.importTask.ImportTaskTypeEnum;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.utils.ExcelUtils;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.common.UploadVo;
import com.wei.czz.framework.common.entity.ImportTaskEntity;
import com.wei.czz.framework.common.service.*;
import com.wei.czz.framework.common.wrapper.MinioWrapper;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2024-11-24 15:22:50
 * className: ImportTaskHelper
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class ImportTaskHelper {

    private static final Logger log = LoggerFactory.getLogger(ImportTaskHelper.class);

    private final ImportTaskService importTaskService;

    private final TransactionService transactionService;

    private final MinioWrapper minioWrapper;

    /**
     * 构造同步导入结果
     * @param successList 解析成功列表
     * @param failList    解析失败列表
     * @param clazz       解析失败列表
     * @return 导入结果对象
     */
    public <T extends UploadVo> UploadDto<T> buildSyncUploadDto(ImportTaskTypeEnum importTaskTypeEnum,
                                                                 List<T> successList,
                                                                 List<T> failList,
                                                                 Class<T> clazz) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        int total = successList.size() + failList.size();

        // 文件类型
        String contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

        // minio文件编号
        Long successFileNo = CommonEnum.MINUS_ONE.getLongValue();
        Long failFileNo = CommonEnum.MINUS_ONE.getLongValue();

        /*
            导入成功数据写入文件
         */
        if (!successList.isEmpty()) {
            String fileName = importTaskTypeEnum.getName() + "成功数据" + FileTypeEnum.XLSX.getSuffix();
            log.info("导入成功数据写入文件 fileName={}", fileName);

            T uploadVo = successList.get(0);

            Consumer<OutputStream> consumer = outputStream -> {
                // 写文件
                ExcelUtils.writeOutputStream("导入成功数据", successList, uploadVo.getTemplatePropertyList(),
                        clazz, ExcelUtils.basicWriteHandlerList(), outputStream);
            };

            /*
                上传excel到minio
             */
            successFileNo = minioWrapper.uploadFile(consumer, fileName, contentType);

        }

        /*
            导入失败数据写入文件
         */
        if (!failList.isEmpty()) {
            String fileName = importTaskTypeEnum.getName() + "失败数据" + FileTypeEnum.XLSX.getSuffix();
            log.info("导入失败数据写入文件 fileName={}", fileName);

            Consumer<OutputStream> consumer = outputStream -> {
                // 写文件
                ExcelUtils.writeOutputStream("导入失败数据", successList, null, clazz,
                        ExcelUtils.basicWriteHandlerList(), outputStream);
            };

            /*
                上传excel到minio
             */
            failFileNo = minioWrapper.uploadFile(consumer, fileName, contentType);

        }

        /*
            保存导入任务
         */
        ImportTaskEntity importTask = new ImportTaskEntity();
        importTask.setType(importTaskTypeEnum.getValue())
                .setMode(TaskModeEnum.SYNC.getValue())
                .setFileType(FileTypeEnum.XLSX.getValue())
                .setDataRow(total)
                .setSuccessRow(successList.size())
                .setFailRow(failList.size())
                .setSuccessFileNo(successFileNo)
                .setFailFileNo(failFileNo)
                .setStatus(CommonEnum.ONE.getValue())
                .setDeleteStatus(CommonEnum.ZERO.getValue())
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                .setCreateTime(date)
                .setCreateUser(userPo.getUsername())
                .setCreateUserId(userPo.getUserId());
        transactionService.execute(() -> importTaskService.saveOrEdit(importTask));

        /*
            返回错误文件key改为返回错误文件下载地址，前端可以通过下载地址直接下载文件
         */
        String downloadFailFileUrl = StringUtils.EMPTY;
        List<NameValue<String>> fieldList = null;
        if (!CommonEnum.MINUS_ONE.getLongValue().equals(failFileNo)) {
            /*
                生成导入失败数据文件下载地址
                有效期1小时
             */
            downloadFailFileUrl = minioWrapper.buildDownloadUrl(failFileNo, 1, TimeUnit.HOURS);

            if (failList.size() < 50) {
                fieldList = failList.get(0).getFailPropertyList();
            }
        }

        UploadDto<T> uploadDto = new UploadDto<>();
        uploadDto.setMode(CommonEnum.ONE.getValue())
                .setTotalCount(total)
                .setSuccessCount(successList.size())
                .setFailedCount(failList.size())
                .setDownloadFailFileUrl(downloadFailFileUrl)
                .setFieldList(fieldList)
                .setFailList(Objects.nonNull(fieldList) ? failList : null);
        return uploadDto;
    }
}
